package videobuy

import (
	"context"
	"fmt"
	"gitee.com/bobo-rs/creative-framework/pkg/utils"
	"gitee.com/bobo-rs/innovideo-services/enums"
	"gitee.com/bobo-rs/innovideo-services/framework/dao"
	"gitee.com/bobo-rs/innovideo-services/framework/model"
	"gitee.com/bobo-rs/innovideo-services/framework/model/entity"
	"gitee.com/bobo-rs/innovideo-services/framework/service"
	"gitee.com/bobo-rs/innovideo-services/framework/validate"
	"gitee.com/bobo-rs/innovideo-services/library/exception"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"strings"
	"time"
)

// GetBillList 获取视频购买账单列表
func (b *sVideoBuy) GetBillList(ctx context.Context, where model.VideoBuyBillListWhere) (rows []model.VideoBuyBillListItem, err error) {
	// 获取数据
	err = dao.VideoBuyBill.Ctx(ctx).
		OmitEmpty().
		Where(where).
		OrderDesc(dao.VideoBuyBill.Columns().Id).
		Scan(&rows)
	return
}

// GetBillDetail 获取视频购买账单详情
func (b *sVideoBuy) GetBillDetail(ctx context.Context, billId uint) (out *model.VideoBillDetailOutput, err error) {
	out = &model.VideoBillDetailOutput{}
	// 获取账单详情
	err = b.BillModel().DetailPri(ctx, billId, &out.VideoBuyBillDetailItem)
	if err != nil {
		return nil, err
	}

	// 获取账单剧集
	err = b.EpisodesModel().Scan(ctx, g.Map{
		dao.VideoBuyEpisodes.Columns().BillId: billId,
	}, &out.EpisodesList)
	return
}

// GenBuyBillAndGetId 生成视频购买账单并获取账单ID
func (b *sVideoBuy) GenBuyBillAndGetId(ctx context.Context, item entity.VideoBuyBill) (uint, error) {
	// 生成账单
	id, err := dao.VideoBuyBill.Ctx(ctx).
		OmitEmpty().
		InsertAndGetId(item)
	if err != nil {
		return 0, exception.Newf(`生成购买账单失败 %s`, err.Error())
	}
	return uint(id), nil
}

// RefundVideoBill 视频账单退款
func (b *sVideoBuy) RefundVideoBill(ctx context.Context, in model.RefundVideoBillInput) error {
	detail, err := validate.CheckVideoBillRefund(ctx, in)
	if err != nil {
		return err
	}

	item := model.PrepareRefundBillItem{
		BillDetail:    detail,
		RefundCoins:   in.RefundCoins,
		EpisodesIdSet: in.EpisodesIdSet,
		Status:        enums.VideoBuyBillStatusPartRefund, // 部分退款
	}
	// 退款盘古币等于支付盘古币，全额退款（支付盘古币 == 本次退款盘古币+之前退款盘古币），
	if detail.BuyPanguCoin == (in.RefundCoins + detail.RefundPanguCoin) {
		item.Status = enums.VideoBuyBillStatusRefund
	}

	// 获取剧集列表
	episodes, err := b.GetBuyEpisodesList(ctx, model.VideoBuyEpisodesWhereItem{
		BillId:     []uint{in.BillId},
		EpisodesId: in.EpisodesIdSet,
	})
	if err != nil {
		return err
	}
	// 获取退款的剧集名称
	item.EpisodesContent = strings.Join(utils.NewArray(episodes).Strings(dao.VideoBuyEpisodes.Columns().EpisodesName), `,`)

	// 退款处理
	return b.BillRefundWithTX(ctx, item)
}

// BillRefundWithTX 视频账单退款-事物处理
func (b *sVideoBuy) BillRefundWithTX(ctx context.Context, item model.PrepareRefundBillItem) error {
	// 事物处理
	return dao.VideoBuyBill.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		//更新账单数据
		_, err := dao.VideoBuyBill.Ctx(ctx).
			Where(dao.VideoBuyBill.Columns().Id, item.BillDetail.Id).
			Update(g.Map{
				dao.VideoBuyBill.Columns().RefundPanguCoin: gdb.Raw(fmt.Sprintf(
					`%s + %d`, dao.VideoBuyBill.Columns().RefundPanguCoin, item.RefundCoins),
				),
				dao.VideoBuyBill.Columns().Status:   item.Status,
				dao.VideoBuyBill.Columns().Remark:   item.BillDetail.Remark + item.EpisodesContent,
				dao.VideoBuyBill.Columns().RefundAt: time.Now().Format(time.DateTime),
			})
		if err != nil {
			return exception.New(`视频账单退款失败 %w`, err)
		}

		// 更新购买信息盘古币
		_, err = dao.VideoBuy.Ctx(ctx).
			Where(dao.VideoBuy.Columns().Id, item.BillDetail.BuyId).
			Decrement(dao.VideoBuy.Columns().AddPanguCoin, item.RefundCoins)
		if err != nil {
			return exception.New(`同步更新账单购买数据失败 %w`, err)
		}

		// 移除购买剧集
		if err = b.DeletePurchasedEpisodes(ctx, item.BillDetail.Id, item.EpisodesIdSet); err != nil {
			return err
		}

		// 增加用户盘古币
		return service.PgCoin().GenPGCoinBill(ctx, model.PGCoinRechargeBillInput{
			Uid:               item.BillDetail.Uid,
			RechargePanguCoin: item.RefundCoins,
			Type:              enums.PGCoinBillTypeSaleRefund,
			Remark:            fmt.Sprintf(`[%d]%s`, item.BillDetail.Id, item.EpisodesContent),
		})
	})
}
